package com.tanger.common.files;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>类名称：OSSObject</p>
 * <p>类描述：OSS文件操作</p>
 * <p>@author cloudkg</p>
 * <p>@version 1.0 2015年9月5日下午3:41:10</p>
 */
public class OSSObject {
	
	private static final Logger log = LoggerFactory.getLogger(OSSObject.class);

	private OSSClient client ;
	
	public OSSObject(){
	    // 初始化OSSClient
	    client = new OSSClient(FilesConfig.endpoint, FilesConfig.accessKeyId, FilesConfig.accessKeySecret);
	}
	
	/**
	 * <p>标题：OSS文件上传 </p>
	 * <p>说明： TODO</p>
	 * @version 1.0  2015年9月5日 下午4:19:31
	 * @param key 文件路径/文件名 (文件路径不存在，则直接文件名。如果有重复，则直接覆盖）
	 * @param filePath 要上传的文件路径
	 * @return	true：文件上传成功	false:文件上传失败
	 */
	public boolean putObject(String key, String filePath) {
		try{
		    // 获取指定文件的输入流
		    File file = new File(filePath);
		    InputStream content = new FileInputStream(file);
	
		    // 创建上传Object的Metadata
		    ObjectMetadata meta = new ObjectMetadata();
	
		    // 必须设置ContentLength
		    meta.setContentLength(file.length());
	
		    // 上传Object.
		    client.putObject(FilesConfig.bucketName, key, content, meta);
	
		    // 打印ETag
//		    System.out.println(result.getETag());
		}catch(FileNotFoundException e){
			e.printStackTrace();
			log.error("=====================上传文件至阿里云：", e);
			return false;
		}catch(OSSException e){
			e.printStackTrace();
			log.error("=====================上传文件至阿里云：", e);
			return false;
		}
		return true;
	}

	/**
	 * 上传文件
	 *
	 * @param key    文件路径，带路径和文件名称
	 * @param in     文件流
	 * @return boolean
	 */
	public boolean putObject(String key, InputStream in) {
		try {
			// 创建上传Object的Metadata
			ObjectMetadata meta = new ObjectMetadata();
			// 必须设置ContentLength
			meta.setContentLength(in.available());
			// 上传Object.
			client.putObject(FilesConfig.bucketName, key, in, meta);
		} catch (IOException e) {
			log.error("OSS 上传文件 {} 出错: {}", key, e.getMessage());
			return false;
		}
		return true;
	}

	/**
	 * 上传文件
	 * @param key    文件路径，带路径和文件名称
	 * @param in     文件流
	 * @param meta
	 * @return boolean
	 */
	public boolean putObject(String key, InputStream in,ObjectMetadata meta) {
		try {
			// 上传Object.
			client.putObject(FilesConfig.bucketName, key, in, meta);
		} catch (Exception e) {
			log.error("OSS 上传文件 {} 出错: {}", key, e.getMessage());
			return false;
		}
		return true;
	}

	/**
	 * <p>标题：OSS文件上传 </p>
	 * <p>说明： TODO</p>
	 * @version 1.0  2015年9月5日 下午4:19:31
	 * @param key 文件路径/文件名 (文件路径不存在，则直接文件名。如果有重复，则直接覆盖）
	 * @return	true：文件上传成功	false:文件上传失败
	 */
	public boolean putObject(String key, File file) {
		try{
			// 上传Object.
			client.putObject(FilesConfig.bucketName, key, file);
		}catch(OSSException e){
			e.printStackTrace();
			log.error("=====================上传文件至阿里云：", e);
			return false;
		}
		return true;
	}



	/**
	 * <p>标题：OSS文件复制</p>
	 * <p>说明： TODO</p>
	 * @version 1.0  2015年9月5日 下午5:21:19
	 * @param srcKey	原文件位置
	 * @param destKey	复制后文件位置
	 * @return	true：成功	false：失败
	 */
	public boolean copyObject(String srcKey, String destKey) {
		try{
		    // 拷贝Object
		    client.copyObject(FilesConfig.bucketName, srcKey, FilesConfig.bucketName, destKey);
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * <p>标题：OSS文件复制 </p>
	 * <p>说明： 复制成功后删除原文件</p>
	 * @version 1.0  2015年9月5日 下午5:21:19
	 * @param srcKey	原文件位置
	 * @param destKey	复制后文件位置
	 * @return	true：成功	false：失败
	 */
	public boolean copyObjectDel(String srcKey, String destKey) {
		try{
		    // 拷贝Object
		    client.copyObject(FilesConfig.bucketName, srcKey, FilesConfig.bucketName, destKey);
		    //删除原文件
		    client.deleteObject(FilesConfig.bucketName, srcKey);
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}
		return true;
	}	
	
	/**
	 * <p>标题： OSS文件删除</p>
	 * <p>说明： 如果文件存在，则直接删除；如果文件不存在，则不做处理</p>
	 * @version 1.0  2015年9月5日 下午4:38:26
	 * @param key 文件路径/文件名
	 * @return true:文件删除成功	false:文件删除失败
	 */
	public boolean deleteObject(String key){
		try{
			client.deleteObject(FilesConfig.bucketName, key);
		}catch(OSSException e){
			e.printStackTrace();
			return false;
		}
		return true;
	}


	/**
	 * 获取文件夹下所有的文件
	 * @param srcKey 文件夹信息 (xxx/xxx/)
	 * @return
	 */
	public List<String> getFiles(String srcKey){
		ListObjectsRequest listObjectsRequest = new ListObjectsRequest(FilesConfig.bucketName);
		listObjectsRequest.setPrefix(srcKey);
		ObjectListing listing = client.listObjects(listObjectsRequest);

		List<String> files = new ArrayList<>();
		for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
			files.add(objectSummary.getKey());
		}

		return files;
	}

	public String getContent(String key) throws IOException {
		com.aliyun.oss.model.OSSObject object = client.getObject(FilesConfig.bucketName, key);
		InputStream in = object.getObjectContent();
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		int ch;
		while ((ch = in.read()) != -1) {
			outStream.write(ch);
		}
		byte[] bytes = outStream.toByteArray();
		return new String(bytes,"utf-8");
	}
}
